/**
 * @file ccsds.h
 *
 * @details
 * The CCSDS class defines operations and data manipulation of CCSDS formatted packets.
 *
 * This header file contains the definitions for the class.
 *
 * @todo
 */

#ifndef CCSDS_H_
#define CCSDS_H_

#include <ctime>
#include <cstring>

const unsigned short MAX_APID = 2048;
const unsigned short MAX_SEQ_COUNT = 16384;
/**
 * CCSDS Packet Version Definition (3 bits).
 */
enum version {
	VERSION_ONE_CCSDS = 0		// CCSDS Standard Space Packet
};

/**
 * CCSDS Packet Type Definition (1 bit).
 */
enum packet_type {
	PACKET_TYPE_TELEMETRY = 0,		// CCSDS Standard definition
	PACKET_TYPE_TELECOMMAND			// CCSDS Standard definition
};

/**
 * CCSDS Packet Secondary Header Definition (1 bit).
 */
enum sec_hdr_flag {
	SECONDARY_HDR_OFF = 0,			// CCSDS Standard definition
	SECONDARY_HDR_ON				// CCSDS Standard definition
};

/**
 * CCSDS Packet Application Process IDs definitions for support software (11 bits).
 * These are custom defined for JETi printers.
 */
enum apid {
	APID_GENERIC = 0x0000,
	APID_SIM_CMD,
	APID_SIM_LOG,
	APID_SIM_GUI,
	APID_RESERVED1 = 0x07FC,
	APID_RESERVED2 = 0x07FD,
	APID_IDLE      = 0x07FF
};

/**
 * CCSDS Packet sequence flags.
 */
enum sequence_flags {
	SEQ_CONTINUATION_SEGMENT = 0x00,		// CCSDS Standard definition
	SEQ_FIRST_SEGMENT        = 0x01,		// CCSDS Standard definition
	SEQ_LAST_SEGMENT         = 0x02,		// CCSDS Standard definition
	SEQ_NO_SEGMENT           = 0x03			// CCSDS Standard definition
};

/**
 * CCSDS Packet Primary Header definition.  Conforms to CCSDS standard for version 1 space packets.
 */
struct CcsdsPrimaryHeader {
	unsigned short packet_version_number	:3;		// CCSDS Standard field
	unsigned short packet_type				:1;		// CCSDS Standard field
	unsigned short secondary_hdr_flag		:1;		// CCSDS Standard field
	unsigned short apid						:11;	// CCSDS Standard field
	unsigned short sequence_flags			:2;		// CCSDS Standard field
	unsigned short packet_sequence_count	:14;	// CCSDS Standard field
	unsigned short packet_data_length		:16;	// CCSDS Standard field
};

/**
 * CCSDS Packet Secondary Header definition.  Does not conform to CCSDS standard for version 1 space packets.  Will use
 * a standard 32 bit Linux timestamp.  If we move to a 64 bit version, we can use the "reserved" field.  The ancillary
 * fields are custom to our printer types.
 */
struct CcsdsSecondaryHeader {
	unsigned int 	reserved;
	time_t 			timestamp;			// Uses standard 32 bit Linux timestamp
	unsigned int	anc_reserved[10];	// Custom ancillary data field
};

/**
 * CCSDS Packet data field definition.  Conforms to CCSDS standard for version 1 space packets for
 * data lengths less than 65536 bytes.
 */
struct CcsdsData {
	char* data;
};

/**
 * CCSDS Packet definition.  Conform to CCSDS standard for version 1 space packets except for the
 * secondary header definitions.
 */
struct CcsdsPacket {
	CcsdsPrimaryHeader ccsdsPriHdr;
	CcsdsData ccsdsData;
	unsigned short ccsdsPacketCrc;
};

/**
 * CCSDS Packet definition.  Conform to CCSDS standard for version 1 space packets except for the
 * secondary header definitions.
 */
struct CcsdsPacketSecHdr {
	CcsdsPrimaryHeader ccsdsPriHdr;
	CcsdsSecondaryHeader ccsdsSecHdr;
	CcsdsData ccsdsData;
	unsigned short ccsdsPacketCrc;
};

/**
 * Defines operations for a CCSDS packet with no secondary header.
 */
class Ccsds {
private:
	CcsdsPacket ccsdsPacket;
protected:
	unsigned short apid_pkt_seq_count_table[MAX_APID];
	void CcsdsSetPktType( unsigned short packet_type );
	void CcsdsSetApid( unsigned short apid );
	void CcsdsSetSeqCount( unsigned short apid );
	void CcsdsSetMsgData( char* msg, unsigned int msg_size );
public:
	Ccsds( void );
	~Ccsds( void );
	unsigned short CcsdsGetVersion( void );
	unsigned short CcsdsGetPktType( void );
	unsigned short CcsdsGetSecHdrFlag( void );
	unsigned short CcsdsGetApid( void );
	unsigned short CcsdsGetSeqFlags( void );
	unsigned short CcsdsGetSeqCount( unsigned short apid );
	unsigned short CcsdsGetPktLength( void );
	void CcsdsCreatePacket( unsigned short packet_type, unsigned short apid, char* msg, unsigned int msg_size );
	void CcsdsPacketDump( void );
	bool CcsdsWrite(char const *);
	unsigned int CcsdsSizeof(unsigned char const *);
	unsigned int CcsdsHashCalc(unsigned char const *);
	unsigned int CcsdsHashWrite(unsigned char const *);
	unsigned int CcsdsHashRead(unsigned char const *);
	bool CcsdsHashCompare(unsigned char const *, unsigned char const *);
};

#endif /* CCSDS_H_ */
